package com.crawler.harbour.task;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.crawler.utils.BeanUtils;
import com.crawler.utils.RedisManager;
import com.crawler.harbour.common.DockCode;
import com.crawler.harbour.model.Notice;
import com.crawler.harbour.model.ShipmentNew;
import com.crawler.harbour.service.INoticeService;
import com.crawler.harbour.service.IShipmentNewService;
import com.crawler.harbour.utils.RuoKuai;
import com.crawler.harbour.utils.StorageDay;
import com.crawler.harbour.utils.UrlUtil;
import com.crawler.utils.StringUtils;
import com.google.common.collect.Maps;

import net.dongliu.requests.Cookie;
import net.dongliu.requests.Requests;
import net.dongliu.requests.Response;
import net.dongliu.requests.Session;


/**
 * 嵩屿码头
 *
 * @author wbsheng
 * @create 2018-03-30 17:22
 **/
@Service
@Lazy(false)
public class XSCTTask extends StorageDay{

    private static final Logger LOGGER = LoggerFactory.getLogger(XSCTTask.class);
    @Autowired
    IShipmentNewService shipmentNewService;
    @Autowired
    private INoticeService noticeService;

    /**
     * 嵩屿码头进箱计划
     */
    @Scheduled(cron = "0 0 0/2 * * ?")
    public void boxPlanning() throws Exception {
    	if(!RedisManager.lock("ship:boxPlanning", 0)) {
    		return;
    	}
        Session session = Requests.session();
        Response<String> stringResponse = session.get(UrlUtil.XSCTINBOX).send().toTextResponse();
        String sessionId = stringResponse.getCookie("ASP.NET_SessionId").getValue();

        Map<String, String> queryMap = new HashMap();
        String[] params = new String[]{"routeNo",
                "routeName",
                "shipCnName",
                "shipEnName",
                "inVoyage",
                "outVoyage",
                "berthing",
                "unberthing",
                "berthingPlan",
                "unberthingPlan",
                "openPortTime",
                "boxCutOff",
                "fumigationBoxTime",
                "customsClearanceTime",
                "wharfInterceptingTime",
                "agent"};
        String[] queryParams = new String[]{"__EVENTTARGET",
                "__EVENTARGUMENT",
                "__VIEWSTATE",
                "__VIEWSTATEGENERATOR",
                "__VIEWSTATEENCRYPTED",
                "__EVENTVALIDATION",
                "ddlLine",
                "txtName",
                "txtVoyage",
                "ddlAgent",
                "ddlPortType",
                "iptStartTime",
                "iptSuffocatingTime",
                "iptCustomTime",
                "iptEndTime",
                "hdMonth",
                "ddlExportType",
                "DropDownList1"};
        //当前页数
        Integer nowPage = 1;
        Integer totalPage = 2;
        while (nowPage <= totalPage) {
            Document doc = getDocument(queryMap, sessionId, session);
            //解析查询表单
            Element queryForm = doc.getElementById("form1");
            Elements inputs = queryForm.getElementsByTag("input");
            for (Element input : inputs) {
                String name = input.attr("name");
                String value = input.attr("value");
                if (Arrays.asList(queryParams).contains(name)) {
                    queryMap.put(name, value);
                }
            }
            //解析总页数
            Element lblCount = doc.getElementById("lblCount");
            String regEx = "[^0-9]";
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher(lblCount.text());
            Integer totalCount = Integer.parseInt(m.replaceAll("").trim());
            //总页数
            totalPage = totalCount / 10 + (totalCount % 10 == 0 ? 0 : 1);
            LOGGER.info("当前页：" + nowPage + "  总页数：" + totalPage + "  总条数：" + totalCount);
            //解析数据表格
            Element table = doc.getElementById("gvVessel");
            Elements trs = table.getElementsByTag("tr");
            int i = 0;
            LOGGER.info("获取行数：" + trs.size());
            for (Element tr : trs) {
                i++;
                //去除最后一行的分页
                if (i == trs.size() - 1) {
                    break;
                }
                Elements tds = tr.getElementsByTag("td");
                Date date = new Date();
                List<String> IdList =new ArrayList<>();
                if (tds != null && tds.size() > 0) {
                    //  去除挂靠港
                    Map<String, String> planMap = new HashMap<>();
                   // XsctBoxPlan xsctBoxPlan = new XsctBoxPlan();
                    for (int j = 0; j < tds.size() - 1; j++) {
                        planMap.put(params[j], tds.get(j).text());
                    }
                 //   BeanUtils.populate(xsctBoxPlan, planMap);
                    
                    ShipmentNew shipmentNew = new ShipmentNew();
                    String hashStr = RuoKuai.MD5(DockCode._SYT+toString(planMap.get("shipEnName"))+toString(planMap.get("inVoyage"))+"_1");
                    shipmentNew.setId(hashStr);
                    ShipmentNew temp = shipmentNewService.selectById(shipmentNew.getId());
                    Notice notice = new Notice();
                    notice.setCreateTime(date);
                   
                   /* //航线代码航线名称进口航次出口航次
                    String hashStr = RuoKuai.MD5(xsctBoxPlan.getShipEnName()+xsctBoxPlan.getShipCnName()+xsctBoxPlan.getInVoyage()+xsctBoxPlan.getOutVoyage());
                    xsctBoxPlan.setId(hashStr);
                    XsctBoxPlan temp = xsctBoxPlanService.selectById(hashStr);
                    Notice notice = new Notice();*/
                    notice.setPortNo(DockCode._SYT);
                    notice.setShipName(toString(planMap.get("shipEnName")));
                    notice.setShipCnName(toString(planMap.get("shipCnName")));
                    notice.setJkShipTimer(toString(planMap.get("inVoyage")));
                    notice.setCkShipTimer(toString(planMap.get("outVoyage")));
                    notice.setJkSailingDate(convertTime(toString(planMap.get("berthingPlan"))));
                    notice.setCkSailingDate(convertTime(toString(planMap.get("unberthingPlan"))));
                    notice.setIntoDate(convertTime(toString(planMap.get("openPortTime"))));
                    notice.setOffDate(convertTime(toString(planMap.get("boxCutOff"))));
                    notice.setBerthDate(convertTime(toString(planMap.get("berthingPlan"))));
                    notice.setLeaveDate(convertTime(toString(planMap.get("unberthingPlan"))));
                    notice.setCutOffDate(convertTime(toString(planMap.get("customsClearanceTime"))));
                    notice.setStatus(0);
                    if(StringUtils.isNullOrEmpty(notice.getShipName())) {
                    	notice.setShipName(notice.getShipCnName());
                    }
                    shipmentNew.setWharfName("嵩屿码头");
                    shipmentNew.setShipTimer(toString(planMap.get("inVoyage")));
//                    shipmentNew.setCustCutDate(convertTime(toString(planMap.get("boxCutOff"))));
                    BeanUtils.copyProperties(notice,shipmentNew , "id","status","type","shipTimer","sailingDate");
                    
                    
                    shipmentNew.setType(1);
                    shipmentNew.setSailingDate(notice.getJkSailingDate());
                    shipmentNewService.insertOrUpdateAllColumn(shipmentNew);
                    hashStr = RuoKuai.MD5(DockCode._SYT+toString(planMap.get("shipEnName"))+toString(planMap.get("outVoyage"))+"_2");
                    shipmentNew.setId(hashStr);
                    shipmentNew.setShipTimer(toString(planMap.get("outVoyage")));
                    shipmentNew.setSailingDate(notice.getCkSailingDate());
                    ShipmentNew temp2 = shipmentNewService.selectById(shipmentNew.getId());
                    shipmentNew.setType(2);
                    shipmentNewService.insertOrUpdateAllColumn(shipmentNew);
                    
                    boolean isOk = true;
	  		        if(temp!=null&&IdList.contains(temp.getId())||temp2!=null&&IdList.contains(temp2.getId())) {
	  		        	isOk = false;
	  		        }
	  		        if(isOk) {
	                    	if(temp !=null && !temp.getSailingDate().equals(notice.getBerthDate())){
	                    		if(toString(temp.getSailingDate()).equals("")) {
	                    			notice.setType(0);
	                    		}else {
	                    			notice.setType(4);
	                            }
	                            notice.setId(null);
	                            notice.setOrigValue(temp.getSailingDate());
	                            noticeService.insert(notice);
	                        }
	                    	 if(temp2 !=null && !temp2.getSailingDate().equals(notice.getLeaveDate())){
	                    		 if(toString(temp2.getSailingDate()).equals("")) {
	                    			 notice.setType(0);
	                    		 }else {
	                    			 notice.setType(1);
	                             }
	                             notice.setId(null);
	                             notice.setOrigValue(temp2.getSailingDate());
	                             noticeService.insert(notice);
	                         }
	                       if(temp2 !=null && !temp2.getIntoDate().equals(notice.getIntoDate())){
	                            notice.setType(3);
	                            notice.setId(null);
	                            notice.setOrigValue(temp2.getIntoDate());
	                            noticeService.insert(notice);
	                        }
	                       if(temp2 !=null && !temp2.getOffDate().equals(notice.getOffDate())){
	                            notice.setType(2);
	                            notice.setId(null);
	                            notice.setOrigValue(temp2.getOffDate());
	                            noticeService.insert(notice);
	                        }
	                       if(temp!=null) {
	                    	   	IdList.add(temp.getId());
	                       	}
	     	              if(temp2!=null) {
	     	            	  	IdList.add(temp2.getId());
	     	              	}
	  		        	
     	              
	  		        }
                }
            }
            //页数+1
            nowPage++;
            queryMap.put("__EVENTARGUMENT", "Page$" + nowPage);
            queryMap.put("__EVENTTARGET", "gvVessel");
            queryMap.put("ddlExportType", "XLS");
            queryMap.put("DropDownList1", "XLS");
            queryMap.put("ddlPortType", "所有");
            queryMap.put("ddlLine", "");
            queryMap.put("ddlAgent", "");
        }
    }


    /**
     * 获取网页
     *
     * @param paramsMap
     * @return
     * @throws Exception
     */
    public Document getDocument(Map<String, String> paramsMap, String sessionId, Session session) throws Exception {
        /* */
        Document document = null;
        if (paramsMap != null && paramsMap.size() > 0) {
            StringBuilder bodyStr = new StringBuilder();
            for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                bodyStr.append(entry.getKey()).append("=");
                bodyStr.append(URLEncoder.encode(entry.getValue(), "utf-8")).append("&");
            }
            bodyStr.deleteCharAt(bodyStr.length() - 1);
            List<Cookie> cookies = new ArrayList<>();
            Cookie cookieNew = new Cookie("www.xsct.com.cn",
                    "/new",
                    "ASP.NET_SessionId",
                    sessionId,
                    10000L,
                    false,
                    false);
            Cookie cookie = new Cookie("www.xsct.com.cn",
                    "/",
                    "ASP.NET_SessionId",
                    sessionId,
                    10000L,
                    false,
                    false);
            cookies.add(cookie);
            cookies.add(cookieNew);
            Map<String,Object> headers = Maps.newHashMap();
            headers.put("Content-Type", "application/x-www-form-urlencoded");
            String body = session.post(UrlUtil.XSCTINBOX).cookies(cookies).headers(headers).body(bodyStr.toString()).send().toTextResponse().getBody();
            document = Jsoup.parse(body);
        } else {
            String body = session.get(UrlUtil.XSCTINBOX).send().toTextResponse().getBody();
            document = Jsoup.parse(body);
        }
        return document;
    }
    
    private String convertTime(String date) {
    	if(StringUtils.isNullOrEmpty(date)) {
    		return "";
    	}
    	return date.replaceAll("\\.", "-");
    	
    }
    private String toString(Object data) {
    	if(data==null) {
    		return "";
    	}
    	return data.toString();
    	
    }
}
